package com.vinoxm.admin.config.token;

import lombok.AllArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import javax.sql.DataSource;
import java.security.KeyPair;
import java.util.Arrays;

@Configuration
public class TokenConfig {

    @Setter(onMethod_ = {@Autowired})
    private DataSource dataSource;

    @Setter(onMethod_ = {@Autowired})
    private ClientDetailsService jdbcClientDetailsService;

    @Setter(onMethod_ = {@Autowired})
    private JwtTokenEnhancer jwtTokenEnhancer;

    @Value("${jwt.sign}")
    private String signKey;

    private final Integer accessTokenExpire;
    private final Integer refreshTokenExpire;

    public TokenConfig(@Value("${jwt.expire.access}") String accessTokenExpire, @Value("${jwt.expire.refresh}") String refreshTokenExpire) {
        this.accessTokenExpire = Arrays.stream(accessTokenExpire.split("\\*")).map(Integer::parseInt).reduce(1, (a, b) -> a * b);
        this.refreshTokenExpire = Arrays.stream(refreshTokenExpire.split("\\*")).map(Integer::parseInt).reduce(1, (a, b) -> a * b);
    }

    /*JDBC管理 token*/
    private TokenStore jdbcTokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    /*JWT管理 token*/
    private TokenStore jwtTokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    /*JWT加密-签名*/
    private JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signKey);
        converter.setAccessTokenConverter(new JwtCustomAccessTokenConverter());
        return converter;
    }

//    @Bean
    public KeyPair keyPair() {
        //从classpath下的证书中获取秘钥对
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray());
        return keyStoreKeyFactory.getKeyPair("jwt", "123456".toCharArray());
    }

    @Bean
    public DefaultTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(jdbcClientDetailsService); // 客户端详情
        service.setSupportRefreshToken(true); // 自动刷新
        service.setAccessTokenValiditySeconds(accessTokenExpire); // accessToken有效期
        service.setRefreshTokenValiditySeconds(refreshTokenExpire); // refreshToken有效期
        service.setTokenStore(jwtTokenStore()); // 存储策略
        // Token增强链
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter(), jwtTokenEnhancer));
        service.setTokenEnhancer(enhancerChain); // Token增强-JWT令牌
        return service;
    }
}
